﻿using System;
using Cysharp.Threading.Tasks;
using UniFramework.Asset;
using UnityEngine;
using UnityEngine.UI;
using YooAsset;
using Object = UnityEngine.Object;

namespace UniFramework.Window
{
	/// <summary>
	/// 每一个Window下面都需要一个Cavans防止重绘影响其他UI
	/// </summary>
	public abstract class UIWindow
	{
		public const int WINDOW_HIDE_LAYER = 2; // Ignore Raycast
		public const int WINDOW_SHOW_LAYER = 5; // UI

		private System.Action<UIWindow> _prepareCallback;
		private System.Object[] _userDatas;

		private bool _isCreate = false;
		private GameObject _panel;
		private Canvas _canvas;
		private Canvas[] _childCanvas;
		private GraphicRaycaster _raycaster;
		private GraphicRaycaster[] _childRaycaster;

		internal AssetLoader _assetLoader;
		public AssetLoader AssetLoader => _assetLoader;

		/// <summary>
		/// 面板的Transfrom组件
		/// </summary>
		public Transform transform => _panel.transform;

		/// <summary>
		/// 面板的游戏对象
		/// </summary>
		public GameObject gameObject => _panel;

		/// <summary>
		/// 窗口名称
		/// </summary>
		public string WindowName { private set; get; }

		/// <summary>
		/// 窗口层级
		/// </summary>
		public int WindowLayer { private set; get; }

		/// <summary>
		/// 是否为全屏窗口
		/// </summary>
		public bool FullScreen { private set; get; }

		/// <summary>
		/// 自定义数据
		/// </summary>
		public System.Object UserData
		{
			get
			{
				if (_userDatas != null && _userDatas.Length >= 1)
					return _userDatas[0];
				else
					return null;
			}
		}

		/// <summary>
		/// 自定义数据集
		/// </summary>
		public System.Object[] UserDatas
		{
			get { return _userDatas; }
		}

		/// <summary>
		/// 窗口深度值
		/// </summary>
		public int Depth
		{
			get
			{
				if (_canvas != null)
					return _canvas.sortingOrder;
				else
					return 0;
			}

			set
			{
				if (_canvas != null)
				{
					if (_canvas.sortingOrder == value)
						return;

					// 设置父类
					_canvas.sortingOrder = value;

					// 设置子类
					int depth = value;
					for (int i = 0; i < _childCanvas.Length; i++)
					{
						var canvas = _childCanvas[i];
						if (canvas != _canvas)
						{
							depth += 5; //注意递增值
							canvas.sortingOrder = depth;
						}
					}

					// 虚函数
					if (_isCreate)
						OnSortDepth(value);
				}
			}
		}

		/// <summary>
		/// <summary>
		/// 窗口可见性
		/// </summary>
		public bool Visible
		{
			get
			{
				if (_canvas != null)
					return _canvas.gameObject.layer == WINDOW_SHOW_LAYER;
				else
					return false;
			}

			set
			{
				if (_canvas != null)
				{
					int setLayer = value ? WINDOW_SHOW_LAYER : WINDOW_HIDE_LAYER;
					if (_canvas.gameObject.layer == setLayer) return;
					// 显示设置
					_canvas.gameObject.layer = setLayer;
					for (int i = 0; i < _childCanvas.Length; i++)
					{
						_childCanvas[i].gameObject.layer = setLayer;
					}

					// 交互设置
					Interactable = value;
					// 虚函数
					if (_isCreate) OnSetVisible(value);
				}
			}
		}

		/// <summary>
		/// 窗口交互性
		/// </summary>
		private bool Interactable
		{
			get
			{
				if (_raycaster != null)
					return _raycaster.enabled;
				else
					return false;
			}

			set
			{
				if (_raycaster != null)
				{
					_raycaster.enabled = value;
					for (int i = 0; i < _childRaycaster.Length; i++)
					{
						_childRaycaster[i].enabled = value;
					}
				}
			}
		}

		// /// <summary>
		// /// 是否加载完毕
		// /// </summary>
		// internal bool IsLoadDone
		// {
		// 	get { return Handle.IsDone; }
		// }

		/// <summary>
		/// 是否准备完毕
		/// </summary>
		internal bool IsPrepare { private set; get; }


		public void Init(string name, int layer, bool fullScreen)
		{
			WindowName = name;
			WindowLayer = layer;
			FullScreen = fullScreen;
		}

		/// <summary>
		/// 窗口创建
		/// </summary>
		public abstract void OnCreate();

		/// <summary>
		/// 窗口刷新
		/// </summary>
		public abstract void OnRefresh();

		/// <summary>
		/// 窗口更新
		/// </summary>
		public abstract void OnUpdate();

		/// <summary>
		/// 窗口销毁
		/// </summary>
		public abstract void OnDestroy();

		/// <summary>
		/// 当触发窗口的层级排序
		/// </summary>
		protected virtual void OnSortDepth(int depth)
		{
		}

		/// <summary>
		/// 异性屏适配
		/// </summary>
		/// <param name="root">改变该对象的offset</param>
		/// <param name="safeRect"></param>
		public virtual void SetAdaptScreen(RectTransform root, Rect safeRect)
		{
			var scaler = _panel.GetComponent<CanvasScaler>();
			float rateX = scaler.referenceResolution.x / Screen.width;
			float rateY = scaler.referenceResolution.y / Screen.height;
			float posX = (int)(safeRect.position.x * rateX);
			float posY = (int)(safeRect.position.y * rateY);
			float width = (int)(safeRect.size.x * rateX);
			float height = (int)(safeRect.size.y * rateY);
			float offsetMaxX = scaler.referenceResolution.x - width - posX;
			float offsetMaxY = scaler.referenceResolution.y - height - posY;
			// 注意：安全区坐标系的原点为左下角
			root.offsetMin = new Vector2(posX, posY); //锚框状态下的屏幕左下角偏移向量
			root.offsetMax = new Vector2(-offsetMaxX, -offsetMaxY); //锚框状态下的屏幕右上角偏移向量
		}

		/// <summary>
		/// 当因为全屏遮挡触发窗口的显隐
		/// </summary>
		protected virtual void OnSetVisible(bool visible)
		{
		}

		internal void TryInvoke(System.Action<UIWindow> prepareCallback, System.Object[] userDatas)
		{
			_userDatas = userDatas;
			if (IsPrepare)
				prepareCallback?.Invoke(this);
			else
				_prepareCallback = prepareCallback;
		}

		internal UniTask<GameObject> InternalLoad(string location, System.Action<UIWindow> prepareCallback,
			System.Object[] userDatas)
		{
			_prepareCallback = prepareCallback;
			_userDatas = userDatas;
			return _assetLoader.LoadAssetsAsync<GameObject>(location, HandleCompleted, handler: this);
		}

		internal void InternalLoadSync(string location, System.Action<UIWindow> prepareCallback,
			System.Object[] userDatas)
		{
			_prepareCallback = prepareCallback;
			_userDatas = userDatas;
			_assetLoader.LoadAssetSync<GameObject>(location, HandleCompleted);
		}

		internal void InternalCreate()
		{
			if (_isCreate == false)
			{
				_isCreate = true;
				OnCreate();
			}
		}

		internal void InternalRefresh()
		{
			OnRefresh();
		}

		internal void InternalUpdate()
		{
			if (IsPrepare)
			{
				OnUpdate();
			}
		}

		internal void InternalDestroy()
		{
			_isCreate = false;
			_prepareCallback = null;
			_assetLoader?.OnDispose();
			_assetLoader = null;
			if (_panel != null)
			{
				OnDestroy();
				GameObject.Destroy(_panel);
				_panel = null;
			}
		}

		private void HandleCompleted(bool success, GameObject asset)
		{
			if (success)
			{
				// 实例化对象
				_panel = Object.Instantiate(asset, UniWindow.Root.transform);
				_panel.transform.localPosition = Vector3.zero;

				// 获取组件
				_canvas = _panel.GetComponent<Canvas>();
				if (_canvas == null)
					throw new Exception($"Not found {nameof(Canvas)} in panel {WindowName}");
				_canvas.overrideSorting = true;
				_canvas.sortingOrder = 0;
				_canvas.sortingLayerName = "Default";

				// 获取组件
				_raycaster = _panel.GetComponent<GraphicRaycaster>();
				_childCanvas = _panel.GetComponentsInChildren<Canvas>(true);
				_childRaycaster = _panel.GetComponentsInChildren<GraphicRaycaster>(true);

				// 通知UI管理器
				IsPrepare = true;
				_prepareCallback?.Invoke(this);
			}
			else
			{
				UniLogger.Error("Failed to create UIWindow");
			}
		}
	}
}